#!/bin/env python

from generator.grammar   import *
from generator.generator import *
from parser.lexer        import Mapper
from parser.reader       import *
from fuzzer              import *
from context             import *


cComma    = SymbolInstance("c,")
cNewLine  = SymbolInstance("cNew Line")
cOpenPar  = SymbolInstance("c(")
cClosePar = SymbolInstance("c)")
cAlt      = SymbolInstance("c|")
cBSlash   = SymbolInstance("c\\")
cOther    = SymbolType("cOther")
cEnd      = SymbolType("cEnd")
cOpenCB   = SymbolType("c{")
cCloseCB  = SymbolType("c}")
cDollar   = SymbolType("c$")

tStr      = SymbolType("[String]")
tComma    = SymbolInstance(",")
tOpenPar  = SymbolInstance("(")
tClosePar = SymbolInstance(")")
tOpenCB   = SymbolInstance("{")
tCloseCB  = SymbolInstance("}")
tDollar   = SymbolInstance("$")
tEscNewLine = SymbolInstance("\\\\n")
tEnd      = SymbolType.tEnd
lElement  = SymbolType("LexerElement")

nDef      = SymbolType("nDef")
nRule     = SymbolType("nRule")
nRules    = SymbolType("nRules")
nArgs     = SymbolType("nArgs")
nItems    = SymbolType("nItems")
nItem     = SymbolType("nItem")

classes = {
    cComma   : ",",
#    cNewLine        : "\n",
    cOpenPar : "(",
    cClosePar: ")",
    cOpenCB  : "{",
    cCloseCB : "}",
#    cDollar  : "$",
#    cBSlash         : "\\",
    SymbolType.tEnd: ""
}

lexerGrammar = Grammar(
    P(
        Rule(tOpenPar, [cOpenPar       ], lambda value: tOpenPar.create(value) ),
        Rule(tClosePar,[cClosePar      ], lambda value: tClosePar.create(value) ),
        Rule(tOpenCB,  [cOpenCB        ], lambda value: tOpenCB.create(value) ),
        Rule(tCloseCB, [cCloseCB       ], lambda value: tCloseCB.create(value) ),
        Rule(tStr,     [cOther         ], lambda value: tStr.create(value)),
        Rule(tStr,     [cOther   ,tStr ], lambda value: tStr.create(value)),
        Rule(tComma,   [cComma         ], lambda value: tComma.create(value)),
        Rule(lElement, [               ], lambda value: tEnd.create(value)  ),
        Rule(lElement, [tStr           ]),
        Rule(lElement, [tComma         ]),
        Rule(lElement, [tOpenPar       ]),
        Rule(lElement, [tClosePar      ]),
        Rule(lElement, [tOpenCB        ]),
        Rule(lElement, [tCloseCB       ])
    ),
    lElement
)

parserGrammar = Grammar(P(
    Rule(nDef  , [nRules        ], lambda ctxt, r   : r          ),
    Rule(nRules, [              ], lambda ctxt      : Empty()    ),
    Rule(nRules, [nRule , nRules], lambda ctxt, r, s: s.append(r)),
    Rule(nRule , [tStr          ], lambda ctxt, s   : Str(s)     ),
    Rule(nRule , [tOpenPar, nItems, tClosePar   ], lambda ctxt, o, i, c   : ctxt.get(i)),
    Rule(nItem , [nRules,tOpenCB,nRules,tCloseCB], lambda ctxt, i, o, r, c: Item(i, r) ),
    Rule(nItem , [nRules                        ], lambda ctxt, r         : Item(r)    ),
    Rule(nItems, [nItem                         ], lambda ctxt, i         : Args(i)    ),
    Rule(nItems, [nItems, tComma, nItem         ], lambda ctxt, s, c, i   : s.append(i)),
), nDef, I(tEscNewLine))

mapper = Mapper(classes, cOther)
lexer  = Lexer(LexerGenerator(lexerGrammar).getStates(), mapper)
parser = Parser(ParserGenerator(parserGrammar).getStates(), lexer)
context = Context()
g = parser.parse(String('a (co,se,3,deje{4}) asd'), context)
#import sys
#g.gen(sys.stdout)
#print